/**
 * Archivo: DiedMerger.java
 * Fecha de creaci&oacute;n: 21/08/2008
 */
package src.logica;

import java.util.Vector;

/**
 * @author Cátedra DIED 2008.
 * 
 */
public class DiedMerger {

	/**
	 * Método encargado de realizar la fusión de las cadenas de entrada, de
	 * acuerdo a los parámetros en <code>parameters</code>.
	 * 
	 * @param input1
	 *            Cadena de entrada.
	 * @param input2
	 *            Cadena de entrada.
	 * @param parameters
	 *            Vector de parámetros; cada uno vendrá de la forma:
	 *            nombre_parametro = valor_paramtero; por ejemplo:
	 *            contarpalabras = true
	 *            Lista de parámetros y sus valores posibles:
	 *            	<li> contarpalabras [true|false]
	 * @return Cadena fusionada.
	 */
	public static String merge(String input1, String input2,Vector<String> parameters) {
		
		long comienzo=System.currentTimeMillis();//tiempo de inicio de la ejecucion de este metodo
		Vector<String> separadores=new Vector<String>();//vector que contiene los criterios por los que se va a separar el string
		int opcion=-1; //bandera elegida 0 si hay que separar por palabras, 1 si es por renglones
		
		System.out.println(); //enter al comienzo para que el log no este en el mismo renglon que cualquier texto previo
		
		separadores.addElement(" |\n");//se agrega espacio en blanco
		separadores.addElement("\n");//se agrega enter
		
		if(parameters.size()>0) //elige el separador que se va a usar
		{
			if(parameters.elementAt(0).equals("contarpalabras = true"))
			{
				opcion=0;
			}
			else
			{
				//TODO aca se agregarian futuras opciones
				return null;
			}
		}
		else
		{
			opcion=1;
		}
		
		String resultado;
		
		String[] texto1=input1.split(separadores.elementAt(opcion));//arreglo de strings que contiene el input1
		String[] texto2=input2.split(separadores.elementAt(opcion));//arreglo de strings que contiene el input2
		
		if(opcion==0)
		{
			resultado= fusionar2dot0(texto1,texto2,opcion,buscarEnters(input1));
		}
		else
		{
			resultado= fusionar2dot0(texto1,texto2,opcion,null);
		}
			
		long fin=System.currentTimeMillis();
		System.out.println("Tiempo de ejecucion: "+(fin-comienzo)+"ms");
		return resultado;
	}
	
	/**
	 * devuelve un vector con las posiciones de los enters en el texto
	 * @param input1
	 * @param input2
	 * @return vector con las posiciones de los enters en un texto
	 */
	private static Vector<Integer> buscarEnters(String input1)
	{
		Vector<Integer> enters=new Vector<Integer>();

		String[] texto1=input1.split(" ");
		int j=0;
		for(int i=0;i<texto1.length;i++)
		{
			j++;
			if(texto1[i].contains("\n"))
			{	
				String[] aux=texto1[i].split("\n");
				for(int h=0;h<aux.length-1;h++)
				{
					enters.addElement(j);
					j++;
				}	
			}
		}
		
		return enters;
	}
	
	
	/**
	 * Va analizando el texto y va guardando en un vector el texto.
	 * @param texto1
	 * @param texto2
	 * @param opcion
	 * @param enters
	 * @return texto fusionado
	 */
	private static String fusionar2dot0(String[] texto1,String[] texto2,int opcion,Vector<Integer> enters)
	{
		int j=0, iIndex=0, iIndex2=0;//indice auxiliar
		VectorDiferencia auxtexto=new VectorDiferencia();//vector que contiene el bloque a agregar del texto 1
		
		//ANALIZAMOS EL TEXTO
		for (int i=0;i<texto1.length;i++)
		{
			if (i< texto2.length)
			{
				if(texto1[i].equals(texto2[j]))
				{
					auxtexto.addElement(texto1[i]);					
					j++;
				}
				else
				{
					iIndex = 0; //TODO ver porq no se tendria q poner j
					while((iIndex<texto2.length) && (!texto1[i].equals(texto2[iIndex])))//mientras las palabras/renglones sean diferentes e iIndex no supere el tamaño del array texto2
					{
						//busco si la linea del texto 2 aparece mas abajo.
						iIndex++;
					}
					//iIndex2 = j+1;//TODO porq j+1?
					iIndex2 = 0;//TODO porq j+1?
					while((iIndex2<texto1.length) && (!texto2[j].equals(texto1[iIndex2])))//mientras las palabras/renglones sean diferentes e iIndex2 no supere el tamaño del array texto1
					{
						//busco si la linea del texto 2 aparece mas abajo.
						iIndex2++;
					}
					if (iIndex == texto2.length && iIndex2 == texto1.length) //cuando hay diferencias en ambos lados
					{
						auxtexto.addElement(new Diferencia(i,texto1[i], 1, true)); //agrege la linea ya que no esta en el texto 2.
						auxtexto.addElement(new Diferencia(j,texto2[j], 2, true)); //agrege la linea ya que no esta en el texto 1.
					}
					else
					{
						if (iIndex == texto2.length) //texto de la izquierda no aparece en el de la derecha
						{
							auxtexto.addElement(new Diferencia(i,texto1[i], 1, false)); //agrege la linea ya que no esta en el texto 2.
						}
						if (iIndex2 == texto1.length)//texto de la derecha no aparece en el de la izquierda
						{
							auxtexto.addElement(new Diferencia(j,texto2[j], 2, false)); //agrege la linea ya que no esta en el texto 2.
						}
					}
					if (i > iIndex)
					{
						if ((iIndex<texto2.length) && texto1[i].equals(texto2[iIndex])) //es cuando las lineas/palabras coinciden
						{
							auxtexto.addElement(texto1[i]);
						}
					}
					//TODO reveer esta seccion.
					if (j > iIndex2)
					{
						if ((iIndex2<texto1.length) && texto2[j].equals(texto1[iIndex2])) //es cuando las lineas/palabras coinciden
						{
							auxtexto.addElement(texto2[j]);
						}
					}
					
					//Incrementamos el contador.
					j++;
				}
			}
			else
			{//El caso que el texto 1 es mas largo que el texto 2
				
				//Busco si los elementos que sobran existe anteriormente en el otro texto.
				iIndex = 0;
				while((iIndex<texto2.length) && (!texto1[i].equals(texto2[iIndex])))//mientras las palabras/renglones sean diferentes e iIndex no supere el tamaño del array de la derecha
				{
					//busco si la linea del texto 2 aparece mas abajo.
					iIndex++;
				}
				if ((iIndex==texto2.length)) //No esta presente en el texto 1.
				{
					auxtexto.addElement(new Diferencia(i,texto1[i], 1, false)); //agrege la linea ya que no esta en el texto 2.
				}
				else if (i > iIndex)
				{
					if ((iIndex<texto2.length) && texto1[i].equals(texto2[iIndex])) //es cuando las lineas/palabras coinciden
					{
						auxtexto.addElement(texto1[i]);
					}
				}
			}	
		}
		//El caso que el texto 2 es mas largo que el texto 1
		if (j < texto2.length)
		{
			for (int k=j; k<texto2.length; k++) //Continuamos donde dejamos el indice j
			{
				//Busco si los elementos que sobran existe anteriormente en el otro texto.
				iIndex = 0;
				while((iIndex<texto1.length) && (!texto2[k].equals(texto1[iIndex])))//mientras las palabras/renglones sean diferentes e iIndex no supere el tamaño del array de la derecha
				{
					//busco si la linea del texto 2 aparece mas abajo.
					iIndex++;
				}
				if ((iIndex==texto1.length)) //No esta presente en el texto 1.
				{
					auxtexto.addElement(new Diferencia(k,texto2[k], 2, false)); //agrege la linea ya que no esta en el texto 2.
				}
				else if (k > iIndex)
				{
					if ((iIndex<texto1.length) && texto2[k].equals(texto1[iIndex])) //es cuando las lineas/palabras coinciden
					{
						auxtexto.addElement(texto2[k]);
					}
				}

			}
		}
		return armar2dot0(opcion,auxtexto,enters);
	}
	
	/**
	 * Arma el log y va a agregando el texto formateado para la salida.
	 * @param opcion
	 * @param auxtexto1
	 * @param enters
	 * @return texto fusionado
	 */
	private static String armar2dot0(int opcion,VectorDiferencia auxtexto, Vector<Integer> enters)
	{
		//ARMAMOS EL RESULTADO
		Vector<String> resultado=new Vector<String>();//al que se le va agregando el texto para mostrar
		String dif; String difFinal;
		int posicionLog=1;
		for (int i=0; i < auxtexto.size(); i++)
		{
			dif =""; difFinal="";
			if ((auxtexto.elementAt(i)) instanceof Diferencia)
			{
				if (((Diferencia)auxtexto.elementAt(i)).getMarcado())//si hay diferencias en los 2 textos
				{
					if(((Diferencia)auxtexto.elementAt(i)).getTextoNro() == 2) //si la palabra esta en el texto2
					{
						if((i<auxtexto.size()-1 && (auxtexto.elementAt(i+1) instanceof Diferencia) && !((Diferencia)auxtexto.elementAt(i+1)).getMarcado() && ((Diferencia)auxtexto.elementAt(i+1)).getTextoNro() == 2) || (i<auxtexto.size()-1 && !(auxtexto.elementAt(i+1) instanceof Diferencia)) || (i == auxtexto.size()-1))
						{
							difFinal = "\n}";
						}
					}
					
					dif = ((Diferencia)auxtexto.elementAt(i)).getTxtLog();					
					resultado.addElement(dif+((Diferencia)auxtexto.elementAt(i)).getLinea()+difFinal);//insertamos la linea en la posicion correspondiente
					if (dif!="")
					{
						posicionLog++;							
					}
					if (opcion==1)//si es por renglones
					{
						System.out.println("La linea "+(((Diferencia)auxtexto.elementAt(i)).getPosicion()+1)+" presente en el documento \"Texto"+ ((Diferencia)auxtexto.elementAt(i)).getTextoNro()+"\" se ha agregado a la salida en la posicion "+posicionLog+".");
					}
					else
					{
						System.out.println("La palabra \""+(((Diferencia)auxtexto.elementAt(i)).getLinea())+"\", presente en el documento \"Texto"+ ((Diferencia)auxtexto.elementAt(i)).getTextoNro()+"\" se ha agregado a la salida");
					}
					
					if (difFinal!="")
					{
						posicionLog++;
					}
				}
				else
				{
					resultado.addElement(dif+((Diferencia)auxtexto.elementAt(i)).getLinea());
					if (opcion==1) //Si es por renglon
					{
						System.out.println("La linea "+(((Diferencia)auxtexto.elementAt(i)).getPosicion()+1)+" presente en el documento \"Texto"+ ((Diferencia)auxtexto.elementAt(i)).getTextoNro()+"\" se ha agregado a la salida en la posicion "+posicionLog+".");
					}
					else
					{
						System.out.println("La palabra \""+(((Diferencia)auxtexto.elementAt(i)).getLinea())+"\", presente en el documento \"Texto"+ ((Diferencia)auxtexto.elementAt(i)).getTextoNro()+"\" se ha agregado a la salida");
					}
					
				}
			}
			else
			{
				resultado.addElement((String)auxtexto.elementAt(i));
			}
			posicionLog++;
		}
			
		String output="";
		for(int i=0;i<resultado.size();i++) //concatena todos los elementos de resultados en un solo string
		{
			if(opcion==0)//agrega espacios o enters dependiendo de la opcion seleccionada
			{
				if(i==enters.elementAt(0))
				{
					output=output+"\n"+resultado.elementAt(i);
					if(enters.size()>1)
					{
						enters.remove(0);
					}
				}
				else
				{
					if(output.equals(""))
					{
						output=resultado.elementAt(i);
					}
					else
					{
						output=output+" "+resultado.elementAt(i);
					}	
				}
			}
			else
			{
				if(i==0) //si es la primera ves que entra al bucle
				{
					output=resultado.elementAt(i);
				}
				else
				{
					output=output+"\n"+resultado.elementAt(i);
				}
			}
		}
		
		if(opcion==0)
		{
			//mostrarLogPalabras(auxtexto1,auxtexto2); //muestra el log cuando se fusiona por palabras
		}
		
		return output;	
	}
	
	
}
